package string;

import org.junit.Test;

/**
 * <P> @Author: ideaAdmin
 * <P> TODO: Class
 * <P> TODO: 字符串拼接操作
 *       1.常量与常量的拼接结果在常量池，原理是编译期优化
 *       *
         * 2.常量池中不会存在相同内容的常量。
         *
         * 3.只要其中有一个是变量，结果就在堆中。变量拼接的原理是StringBuilder
         *
         * 4.如果拼接的结果调用intern ()方法，则主动将常量池中还没有的字符串对象放入池中，并返回此对象地址。
 * <P> Date: 2022/3/20:10:00
 * <P> Description:
 */

public class StringAppend {
    @Test
    public void test1(){
        //编译期优化   String s1 = "abc";
        String s1 = "a" + "b" + "c";
        //放在常量池中,并将地址赋给s2
        String s2 = "abc";
        //true 因为编译器优化
        System.out.println(s1==s2);
    }

    @Test
    public void test2(){
        String s1 = "javaEE";
        String s2 = "hadoop";

        String s3 = "javaEEhadoop";
        String s4 = "javaEE"+"hadoop";
        //如果拼接符合的前后出现了变量 则相当于在堆空间中new String() //拼接后的内容是javaEEhadoop
        String s5 = s1+"hadoop";
        String s6 = "javaEE"+s2;
        String s7 = s1+s2;

        System.out.println(s3==s4);//true 编译器优化
        System.out.println(s3==s5);//false s5-s7返回的都是新的对象
        System.out.println(s3==s6);//false
        System.out.println(s3==s7);//false

        System.out.println(s5==s6);//false
        System.out.println(s5==s7);//false
        System.out.println(s6==s7);//false

        String s8 = s6.intern();
        //intern：判断字符串常量池中是否存在了javaEEhadoop的值，
        //如果存在 则返回常量池中 javaEEhadoop 的地址
        //如果不存在 则在常量池中加载一份 javaEEhadoop 在返回对象地址
        System.out.println(s3 == s8);//true 返回的是s6在常量池中的赋值
        System.out.println(s8 == s6);//false 因为s6对应常量已经在常量池中
                                    // 返回给s8的是已经在常量池的地址 然而s6本身是个对象 所有不等
    }


    @Test
    public void test3(){
        String s1 = "a";
        String s2 = "b";
        String s3 = "ab";
        //如下s1 + s2的指向细节
        // StringBuilder s = new StringBuilder();
        // s.append("a")
        // s.append("b")
        // s.toString() ->约等于 new String()
        String s4 = s1+s2;
        System.out.println(s3==s4);//false
    }

    /**
        * TODO: 字符串拼接操作不一定使用的是stringBuilder ! 如果拼接符号左右两边都是字符串常量或常量引用 仍然使用   编译期优化 非StringBuilder的方式
     *
    **/
    @Test
    public void test4(){
        final String s1 = "a";
        final String s2 = "b";
        String s3 = "ab";

        String s4 = s1+s2;
        //这里的s4 其实是 "a" + "b"
        //因为s1 s2被final修饰 它们已经是常量了 而不是对象了 不会使用 StringBuilder 拼接
        System.out.println(s3==s4);//true
    }

}
